/*
 * LexOrder.java
 *
 * Created on February 5, 2004, 2:09 PM
 */

package com.milowski.monos.monomial;

import java.util.*;
import com.milowski.monos.*;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;


/**
 * Represents a lex order for a set of variables
 * @author  R. Alexander Milowski
 */
public class LexOrder extends ArrayList implements XMLMarshaller {

   // TODO: there has to be a better way!
   Map indexMap;
   /** 
    * Creates a new instance of LexOrder without any variables.  The method
    * add() should be used with a string variable name to add variables to this
    * lexicographic ordering.
    */
   public LexOrder() {
      indexMap = new HashMap();
   }
   
   /**
    * Adds a variable to the order at the end of the ordering.
    * @param o The variable name (as a string).
    * @return A boolean value indicating success.
    */
   public boolean add(Object o) {
      if (!(o instanceof String)) {
         return false;
      }
      String name = (String)o;
      if (!contains(name)) {
         super.add(o);
         indexMap.put(name,new Integer(size()-1));
         return true;
      } else {
         return false;
      }
   }
   
   /**
    * Returns the index in the ordering for the variable name.
    * @param The variable name.
    * @throws IllegalArgumentException Thrown when  the variable name is not in the ordering.
    * @return An index value.
    */
   public int getOrder(String name) {
      Integer value = (Integer)indexMap.get(name);
      if (value==null) {
         throw new IllegalArgumentException("Variable "+name+" is not defined in the current lex order");
      }
      return value.intValue();
   }
   
   /**
    * Projects the ordering by removing the first variable in the ordering.
    * @return A new lexicographic ordering without the first variable.
    */
   public LexOrder project() {
      LexOrder projection = new LexOrder();
      Iterator values = iterator();
      values.next();
      while (values.hasNext()) {
         projection.add((String)values.next());
      }
      return projection;
   }
   
   public String toString() {
      StringBuffer sb = new StringBuffer();
      sb.append("(lex-order");
      for (Iterator toOutput=iterator(); toOutput.hasNext();) {
         sb.append(' ');
         sb.append(toOutput.next().toString());
      }
      sb.append(")");
      return sb.toString();
   }
   
   public void toXML(ItemDestination dest) throws XMLException {
      toXML(InfosetFactory.getDefaultInfoset().createItemConstructor(),dest);
   }

   public void toXML(ItemConstructor constructor, ItemDestination dest) throws XMLException {
      dest.send(constructor.createElement(XML.lexOrderName));
      StringBuffer sb = new StringBuffer();
      int len = size();
      for (int i=0; i<len; i++) {
         if (i!=0) {
            sb.append(' ');
         }
         sb.append(get(i));
      }
      dest.send(constructor.createCharacters(sb.toString()));
      dest.send(constructor.createElementEnd(XML.lexOrderName));
   }
   
}
